package com.cci.kangdao.fieldService.manager.impl;

import com.cci.kangdao.common.ApplicationContextUtils;
import com.cci.kangdao.crmapi.CRMHttpClientUtil;
import com.cci.kangdao.crmapi.CRMServiceConst;
import com.cci.kangdao.fieldService.dao.FieldServiceChannelDao;
import com.cci.kangdao.fieldService.dao.FieldServiceItemDao;
import com.cci.kangdao.fieldService.dao.FieldServiceWorkOrderDao;
import com.cci.kangdao.fieldService.manager.SyncCCGManager;
import com.cci.kangdao.fieldService.manager.dto.request.SyncItemRequest;
import com.cci.kangdao.fieldService.manager.dto.request.SyncWorkOrderReportRequest;
import com.cci.kangdao.fieldService.manager.dto.request.SyncWorkOrderRequest;
import com.cci.kangdao.fieldService.manager.dto.request.SyncWorkOrderStatusRequest;
import com.cci.kangdao.fieldService.manager.dto.response.SyncItemResponse;
import com.cci.kangdao.fieldService.manager.dto.response.SyncResponse;
import com.cci.kangdao.fieldService.manager.dto.response.SyncWorkOrderResponse;
import com.cci.kangdao.fieldService.model.*;
import com.cci.kangdao.fieldService.model.type.FieldServiceUpgradeStatus;
import com.cci.kangdao.fieldService.model.type.FieldServiceUpgradeType;
import com.cci.kangdao.fieldService.model.type.FieldServiceWorkOrderStatus;
import com.cci.kangdao.redis.RedisClientUtils;
import com.cci.kangdao.utilTool.BeanUtils;
import com.cci.kangdao.utilTool.HttpUtils;
import com.cci.kangdao.utilTool.JsonUtils;
import com.cci.kangdao.utilTool.PropertiesUtil;
import net.sf.json.JSONObject;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author William Du
 * @date 2020/1/21
 */
@Service
public class SyncCCGManagerImpl implements SyncCCGManager {

    private static final Logger logger = Logger.getLogger(SyncCCGManagerImpl.class);

    @Resource
    private FieldServiceItemDao fieldServiceItemDao;

    @Resource
    private FieldServiceWorkOrderDao fieldServiceWorkOrderDao;

    @Resource
    private FieldServiceChannelDao fieldServiceChannelDao;

    private String getChannel(Long channelId){
        FieldServiceChannel channel = fieldServiceChannelDao.selectByPrimaryKey(channelId);
        if(null != channel){
            return channel.getChannelNo();
        }
        return null;
    }

    @Override
    public String syncServiceItemFromApp(FieldServiceEngineer engineer, FieldServiceItem fieldServiceItem) {
        logger.info("同步item");
        SyncItemRequest request = BeanUtils.convert(fieldServiceItem, SyncItemRequest.class);
        request.setChannel(getChannel(fieldServiceItem.getChannel()));
        request.setEmployeeNum(engineer.getEmployeeNum());

        // 添加加密请求头
        Map<String, Object> tokenAndHostMap = this.getGGICTokenAndHost();
        // 添加token请求头
        String host = MapUtils.getString(tokenAndHostMap, "hostUrl", "");
        String token = MapUtils.getString(tokenAndHostMap,"token","");
        Header authorizationHeader = new BasicHeader("Authorization",token);

        String url = host+SyncCCGManager.SYNC_ITEM_URL;
        SyncResponse<SyncItemResponse> syncResponse = request(url,request,SyncItemResponse.class,authorizationHeader);
        if(null != syncResponse && syncResponse.getStatus().equals(0)){
            return syncResponse.getData().getItemNo();
        }
        return null;
    }

    @Override
    public String syncServiceOrderFromApp(FieldServiceWorkOrder workOrder) {
        logger.info("同步wo");
        SyncWorkOrderRequest request = BeanUtils.convert(workOrder, SyncWorkOrderRequest.class);
        request.setChannel(getChannel(workOrder.getChannel()));
        FieldServiceItem item = fieldServiceItemDao.selectByPrimaryKey(workOrder.getItemId());
        request.setCrmItemNo(item.getCrmItemNo());

        // 添加加密请求头
        Map<String, Object> tokenAndHostMap = this.getGGICTokenAndHost();
        // 添加token请求头
        String host = MapUtils.getString(tokenAndHostMap, "hostUrl", "");
        String token = MapUtils.getString(tokenAndHostMap,"token","");
        Header authorizationHeader = new BasicHeader("Authorization",token);
        String url = host+SyncCCGManager.SYNC_ORDER_URL;

        SyncResponse<SyncWorkOrderResponse> syncResponse = request(url,request,SyncWorkOrderResponse.class,authorizationHeader);
        if(null != syncResponse && syncResponse.getStatus().equals(0)){
            return syncResponse.getData().getCrmOrderNo();
        }
        return null;
    }

    @Override
    public Boolean syncOrderStatusFromApp(FieldServiceWorkOrder workOrder,String message) {
        SyncWorkOrderStatusRequest request = new SyncWorkOrderStatusRequest();
        request.setChannel(getChannel(workOrder.getChannel()));
        workOrder = fieldServiceWorkOrderDao.selectByPrimaryKey(workOrder.getId());
        request.setWorkOrderNo(workOrder.getWorkOrderNo());
        request.setCrmOrderNo(workOrder.getCrmOrderNo());
        request.setType("1");
        request.setStatus(String.valueOf(workOrder.getStatus()));
        if(FieldServiceWorkOrderStatus.CANCELLED.getCode().equals(workOrder.getStatus())){
            request.setCancelReason(message);
        }

        // 添加加密请求头
        Map<String, Object> tokenAndHostMap = this.getGGICTokenAndHost();
        // 添加token请求头
        String host = MapUtils.getString(tokenAndHostMap, "hostUrl", "");
        String token = MapUtils.getString(tokenAndHostMap,"token","");
        Header authorizationHeader = new BasicHeader("Authorization",token);
        String url = host+SyncCCGManager.SYNC_STATUS_URL;

        SyncResponse syncResponse = request(url,request,authorizationHeader);
        if(null != syncResponse && syncResponse.getStatus().equals(0)){
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    @Override
    public Boolean syncOrderStatusFromApp(FieldServiceUpgrade upgrade) {
        SyncWorkOrderStatusRequest request = new SyncWorkOrderStatusRequest();
        FieldServiceWorkOrder workOrder = fieldServiceWorkOrderDao.selectByPrimaryKey(upgrade.getOrderId());
        request.setChannel(getChannel(workOrder.getChannel()));
        request.setWorkOrderNo(workOrder.getWorkOrderNo());
        request.setCrmOrderNo(workOrder.getCrmOrderNo());
        // 取消升级
        if(FieldServiceUpgradeStatus.CANCEL.getCode().equals(upgrade.getStatus())){
            request.setType("3");
            request.setUpgradeCancelMessage(upgrade.getSolution());
        }else{
            // 请求升级
            request.setType("2");
            if(FieldServiceUpgradeType.REQUEST_CANCEL.getCode().equals(upgrade.getType())){
                // 请求取消
                request.setUpgradeType("1");
                request.setUpgradeMessage(upgrade.getRequest());
            }else if(FieldServiceUpgradeType.REQUEST_RESOURCE.getCode().equals(upgrade.getType())){
                // 请求资源
                request.setUpgradeType("2");
                request.setUpgradeMessage(upgrade.getRequest());
            }else if(FieldServiceUpgradeType.REQUEST_TECHNOLOGY.getCode().equals(upgrade.getType())){
                // 技术升级
                request.setUpgradeType("4");
                request.setUpgradeMessage(upgrade.getRequest());
            }else{
                // 请求延期
                request.setUpgradeType("3");
                request.setUpgradeMessage(upgrade.getRequest());
                request.setUpgradeTime(upgrade.getRequestedEndDate());
            }
        }

        // 添加加密请求头
        Map<String, Object> tokenAndHostMap = this.getGGICTokenAndHost();
        // 添加token请求头
        String host = MapUtils.getString(tokenAndHostMap, "hostUrl", "");
        String token = MapUtils.getString(tokenAndHostMap,"token","");
        Header authorizationHeader = new BasicHeader("Authorization",token);
        String url = host+SyncCCGManager.SYNC_STATUS_URL;

        SyncResponse syncResponse = request(url,request,authorizationHeader);
        if(null != syncResponse && syncResponse.getStatus().equals(0)){
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    @Override
    public Boolean syncReportFromAPP(WorkOrderReport report) {
        FieldServiceWorkOrder workOrder = fieldServiceWorkOrderDao.selectByPrimaryKey(report.getOrderId());
        SyncWorkOrderReportRequest request = BeanUtils.convert(report,SyncWorkOrderReportRequest.class);
        request.setChannel(getChannel(workOrder.getChannel()));
        request.setWorkOrderCrmNo(workOrder.getCrmOrderNo());

        // 添加加密请求头
        Map<String, Object> tokenAndHostMap = this.getGGICTokenAndHost();
        // 添加token请求头
        String host = MapUtils.getString(tokenAndHostMap, "hostUrl", "");
        String token = MapUtils.getString(tokenAndHostMap,"token","");
        Header authorizationHeader = new BasicHeader("Authorization",token);
        String url = host+SyncCCGManager.SYNC_REPORT_URL;

        SyncResponse syncResponse = request(url,request,authorizationHeader);
        if(null != syncResponse && syncResponse.getStatus().equals(0)){
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }
    public Map<String, Object> getGGICTokenAndHost() {
        RedisClientUtils redisClientUtils = (RedisClientUtils) ApplicationContextUtils.getBean("redisClientUtils");
        if (redisClientUtils != null) {
            Map<String, String> redisMap = redisClientUtils.getMap(CRMServiceConst.CRMTOKEN_HOSTURL_CBU);
            if (MapUtils.isEmpty(redisMap)) {
                String tokenUrl = PropertiesUtil.getProperties("projectconfig.properties", "crm.cbu.token.host").trim();
                Map<String, Object> map = new HashMap<>();
                map.put("username", PropertiesUtil.getProperties("projectconfig.properties", "crm.cbu.username").trim());
                map.put("password", PropertiesUtil.getProperties("projectconfig.properties", "crm.cbu.password").trim());
                map.put("client_id", PropertiesUtil.getProperties("projectconfig.properties", "crm.cbu.clientId").trim());
                map.put("client_secret", PropertiesUtil.getProperties("projectconfig.properties", "crm.cbu.clientSecret").trim());
                map.put("grant_type", PropertiesUtil.getProperties("projectconfig.properties", "crm.cbu.grant_type").trim());
                String response = HttpUtils.postJson(tokenUrl, JsonUtils.toJsonString(map), new ResponseHandler<String>() {
                    @Override
                    public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
                        if (response.getStatusLine().getStatusCode() == 200) {
                            HttpEntity httpEntity = response.getEntity();
                            return EntityUtils.toString(httpEntity, "UTF-8");
                        }
                        return null;
                    }
                });
                System.out.println(response);
                JSONObject responseDate = CRMHttpClientUtil.httpPOSTRequest(tokenUrl, null, map);
                if (responseDate != null && responseDate instanceof JSONObject) {
                    if (responseDate.get("token_type") != null && responseDate.get("access_token") != null) {
                        String token = String.format("%s %s", responseDate.get("token_type"), responseDate.get("access_token"));
                        String host = String.format("%s/services/apexrest/", responseDate.get("instance_url"));
                        Map<String, String> hostMap = new HashMap<>();
                        hostMap.put("token", token);
                        hostMap.put("hostUrl", host);
                        redisClientUtils.setMap(CRMServiceConst.CRMTOKEN_HOSTURL_CBU, hostMap, 60 * 6 * 15);
                        return new HashMap<>(hostMap);
                    }

                }
            } else {
                return new HashMap<>(redisMap);
            }
        }
        return null;
    }

    private SyncResponse request(String url, Object request, Class responseClass, Header... header){
        String requestJson = JsonUtils.toJsonStringFilterEmpty(request);
        logger.info("现场工单同步CRM请求："+requestJson);
        String response = HttpUtils.postJson(url, requestJson, new ResponseHandler<String>() {
            @Override
            public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
                if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                    return EntityUtils.toString(response.getEntity());
                }else{
                    return null;
                }
            }
        },header);
        logger.info("现场工单同步CRM响应："+response);
        SyncResponse syncResponse = null;
        if(StringUtils.isNotEmpty(response)) {
            syncResponse = JsonUtils.toJavaObject(response, SyncResponse.class);
            if (null != syncResponse.getData() && null != responseClass) {
                String dataJson = JsonUtils.toJsonString(syncResponse.getData());
                syncResponse.setData(JsonUtils.toJavaObject(dataJson, responseClass));
            }
        }
        return syncResponse;
    }

    private SyncResponse request(String url, Object request, Header... header){
        return request(url,request,null,header);
    }

    public SyncResponse getResponse(String response,Class clazz){
        if(StringUtils.isNotEmpty(response)){
            SyncResponse syncResponse = JsonUtils.toJavaObject(response,SyncResponse.class);
            if(null != syncResponse.getData()){
                String dataJson = JsonUtils.toJsonString(syncResponse.getData());
                syncResponse.setData(JsonUtils.toJavaObject(dataJson,clazz));
            }
            return syncResponse;
        }
        return null;
    }


}
